﻿using Candy.Model;
using Candy.Web.Data;
using GalaSoft.MvvmLight.Command;
using System;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using System.Linq;
using System.Threading.Tasks;
using GalaSoft.MvvmLight.Threading;

namespace Candy.ViewModel
{
    public class BlastHitViewModel : EntityViewModelBase<HitResultDto>
    {
        private bool _asOrtholog = false;
        private bool _asHomolog = true;
        private bool _asRelated = false;
        private bool _justTag = false;

        public bool JustTag
        {
            get
            {
                return _justTag;
            }
            set
            {
                if (_justTag != value)
                {
                    _justTag = value;
                    RaisePropertyChanged("JustTag");
                }
            }
        }

        public bool AsOrtholog
        {
            get
            {
                return _asOrtholog;
            }
            set
            {
                if (_asOrtholog != value)
                {
                    _asOrtholog = value;
                    if (_asOrtholog)
                        Entity.ProposedEntryType = GeneEntryType.ortholog;
                    RaisePropertyChanged("AsOrtholog");
                }
            }
        }
        public bool AsHomolog
        {
            get
            {
                return _asHomolog;
            }
            set
            {
                if (_asHomolog != value)
                {
                    _asHomolog = value;
                    if (_asHomolog)
                        Entity.ProposedEntryType = GeneEntryType.homolog;
                    RaisePropertyChanged("AsHomolog");
                }
            }
        }
        public bool AsRelated
        {
            get
            {
                return _asRelated;
            }
            set
            {
                if (_asRelated != value)
                {
                    _asRelated = value;
                    if (_asRelated)
                        Entity.ProposedEntryType = GeneEntryType.related;

                    RaisePropertyChanged("AsRelated");
                }
            }
        }

        private SolidColorBrush _heatMap = new SolidColorBrush(Colors.Transparent);
        public SolidColorBrush Heat
        {
            get
            {
                return _heatMap;
            }
            set
            {
                _heatMap = value;
                RaisePropertyChanged("Heat");
            }
        }

        public BitmapImage StateImage { get; set; }

        public string ImportActionText { get; set; }
        public string StatusText { get; set; }

        public bool ImportReady { get; set; }
        public bool AllowJustTagging { get; private set; }

        private ImportStatus _status;
        public ImportStatus Status
        {
            get
            {
                return _status;
            }
            set
            {
                DispatcherHelper.CheckBeginInvokeOnUI(() =>
                    {
                        _status = value;
                        switch (_status)
                        {
                            case ImportStatus.READY:
                                {
                                    StateImage = new BitmapImage(new Uri("Images/Icons/Import.png", UriKind.Relative));
                                    ImportActionText = "Import";
                                    StatusText = "Ready to import!";
                                    AllowJustTagging = false;
                                    break;
                                }
                            case ImportStatus.OK:
                                {
                                    StateImage = new BitmapImage(new Uri("Images/Icons/Done.png", UriKind.Relative));
                                    ImportActionText = "Re-Import";
                                    StatusText = "Gene successful imported!";
                                    AllowJustTagging = false;
                                    break;
                                }
                            case ImportStatus.DOUBLEENTRY:
                                {
                                    StateImage = new BitmapImage(new Uri("Images/Icons/Warning.png", UriKind.Relative));
                                    ImportActionText = "Re-Import";
                                    StatusText = string.Format("Gene already imported by gene family {0}, bait {1}!", Entity.AssignedGeneFamilyName, Entity.AssignedBaitName);
                                    AllowJustTagging = true;
                                    break;
                                }
                            case ImportStatus.IMPORTING:
                                {
                                    StateImage = new BitmapImage(new Uri("Images/Icons/Hourglass.png", UriKind.Relative));
                                    ImportActionText = "Importing...";
                                    StatusText = string.Format("Gene gets imported...");
                                    ImportReady = false;
                                    //AllowJustTagging = false;
                                    break;
                                }
                            default:
                                break;
                        }
                        RaisePropertyChanged("StateImage");
                        RaisePropertyChanged("ImportActionText");
                        RaisePropertyChanged("StatusText");
                        RaisePropertyChanged("ImportReady");
                        RaisePropertyChanged("AllowJustTagging");
                        ImportGene.RaiseCanExecuteChanged();
                    });
            }
        }

        BlastTask _blastTask;
        IDataService _dataService;
        public BlastHitViewModel(IDataService dataService, HitResultDto hit, BlastTask blastTask)
            : base(hit)
        {
            _dataService = dataService;
            _blastTask = blastTask;
            if ((hit.AssignedBaitId == null && hit.AssignedGeneId == null) || hit.AssignedGeneFamilyId == null)
                Status = ImportStatus.READY;
            else if (hit.AssignedGeneFamilyId == hit.RequestingGeneFamilyId)
                Status = ImportStatus.OK;
            else if (hit.AssignedGeneFamilyId != hit.RequestingGeneFamilyId)
                Status = ImportStatus.DOUBLEENTRY;
        }


        private RelayCommand _importGene;
        public RelayCommand ImportGene
        {
            get
            {
                return _importGene ?? (_importGene = new RelayCommand(ExecImportGene, CanImportGene));
            }
        }

        /// <summary>
        /// Checks whether the ImportGene command is executable
        /// </summary>
        private bool CanImportGene()
        {
            return Status != ImportStatus.IMPORTING;
        }

        /// <summary>
        /// Executes the ImportGene command 
        /// </summary>
        private void ExecImportGene()
        {
            ImportAsync(null);
            //base.ResetError();
            //base.ReportProgress();
            //Status = ImportStatus.IMPORTING;
            //if (_blastTask == BlastTask.blast_fishing_dbs)
            //{
            //  _dataService.DataContext.ImportCandidateGene(_dataService.LoadedProject.Id, Entity, op =>
            //    {
            //        base.FinishProgress();
            //        if (op.HasError)
            //        {
            //            base.HandleDomainError(op, "Importing gene failed.");
            //            Status = ImportStatus.READY;
            //        }
            //        else
            //        {
            //            _dataService.DataContext.GeneDtos.Attach(op.Value);
            //            Status = ImportStatus.OK;
            //        }
            //    }, null);
            //}
            //if (_blastTask == BlastTask.find_ortholog_genes)
            //{
            //    _dataService.DataContext.ImportSecondaryBait(_dataService.LoadedProject.Id, Entity, op =>
            //    {
            //        base.FinishProgress();
            //        if (op.HasError)
            //        {
            //            base.HandleDomainError(op, "Importing gene failed.");
            //            Status = ImportStatus.READY;
            //        }
            //        else
            //        {
            //            if (_dataService.Genotypes.Any(x => x.Id == op.Value.GenotypeId) == false)
            //            {
            //                //refresh the genotypes
            //                _dataService.RefreshGenotypes(op2 =>
            //                    {
            //                        if (op2.HasError)
            //                            base.HandleDomainError(op2, "Couldn't refresh genotypes.");
            //                        _dataService.DataContext.GeneDtos.Attach(op.Value);
            //                        Status = ImportStatus.OK;
            //                    });
            //            }
            //            else
            //            {
            //                _dataService.DataContext.GeneDtos.Attach(op.Value);
            //                Status = ImportStatus.OK;
            //            }
            //        }
            //    }, null);
            //}
        }

        internal void ImportAsync(Action callback)
        {
            base.ResetError();
            base.ReportProgress();
            Status = ImportStatus.IMPORTING;

            if (_blastTask == BlastTask.blast_fishing_dbs)
            {
                _dataService.DataContext.ImportCandidateGene(_dataService.LoadedProject.Id, Entity, op =>
                {
                    base.FinishProgress();
                    if (op.HasError)
                    {
                        base.HandleDomainError(op, "Importing gene failed.");
                        Status = ImportStatus.READY;
                    }
                    else
                    {
                        var toRemove = _dataService.DataContext.GeneDtos.SingleOrDefault(x => x.GeneIdentifier == op.Value.GeneIdentifier);
                        if (toRemove != null)
                            _dataService.DataContext.GeneDtos.Detach(toRemove);
                        _dataService.DataContext.GeneDtos.Attach(op.Value);
                        Status = ImportStatus.OK;
                    }
                    if (callback != null)
                        callback();
                }, null);
            }
            if (_blastTask == BlastTask.find_ortholog_genes)
            {
                _dataService.DataContext.ImportSecondaryBait(_dataService.LoadedProject.Id, Entity, op =>
                {
                    base.FinishProgress();
                    if (op.HasError)
                    {
                        base.HandleDomainError(op, "Importing gene failed.");
                        Status = ImportStatus.READY;
                    }
                    else
                    {
                        if (_dataService.Genotypes.Any(x => x.Id == op.Value.GenotypeId) == false)
                        {
                            //refresh the genotypes
                            _dataService.RefreshGenotypes(op2 =>
                            {
                                if (op2.HasError)
                                    base.HandleDomainError(op2, "Couldn't refresh genotypes.");
                                _dataService.DataContext.GeneDtos.Attach(op.Value);
                                Status = ImportStatus.OK;
                            });
                        }
                        else
                        {
                            _dataService.DataContext.GeneDtos.Attach(op.Value);
                            Status = ImportStatus.OK;
                        }
                    }
                    if (callback != null)
                        callback();
                }, null);
            }

        }
    }
}
